From da83457a60b4a1f375efb14f06f6be7c45ea0128 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 16 Feb 2020 16:22:37 +0100 Subject: [PATCH] dnd: Remove gdk_content_provider_new_with_callback() Content providers are meant to be immutable, apart from very special cases, but in those cases they need to emit gdk_content_provider_content_changed(). Having a constructor that just uses a get_func invites abuse of this by not making developers aware of those requirments. In fact, all users in GTK failed to do this. Instead, code should use the GtkDragSource::prepare signal to create content providers when needed. The same problem exists with gdk_content_provider_new_with_formats(), but this commit doesn't touch that. --- demos/gtk-demo/clipboard.c | 17 ++--- demos/icon-browser/iconbrowserwin.c | 46 ++++++------ gdk/gdkcontentproviderimpl.c | 112 ---------------------------- gdk/gdkcontentproviderimpl.h | 9 --- gtk/gtkcolorbutton.c | 18 ++--- gtk/gtkcolorswatch.c | 18 ++--- 6 files changed, 48 insertions(+), 172 deletions(-) diff --git a/demos/gtk-demo/clipboard.c b/demos/gtk-demo/clipboard.c index 97d0579f1d..7acc83093d 100644 --- a/demos/gtk-demo/clipboard.c +++ b/demos/gtk-demo/clipboard.c @@ -138,23 +138,18 @@ drag_begin (GtkDragSource *source, } } -static void -get_texture (GValue *value, - gpointer data) -{ - GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data)); - - if (GDK_IS_TEXTURE (paintable)) - g_value_set_object (value, paintable); -} - static GdkContentProvider * prepare_drag (GtkDragSource *source, double x, double y, GtkWidget *image) { - return gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image, NULL); + GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (image)); + + if (!GDK_IS_TEXTURE (paintable)) + return NULL; + + return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable); } static void diff --git a/demos/icon-browser/iconbrowserwin.c b/demos/icon-browser/iconbrowserwin.c index d094c029d1..28731b6e43 100644 --- a/demos/icon-browser/iconbrowserwin.c +++ b/demos/icon-browser/iconbrowserwin.c @@ -406,47 +406,53 @@ drag_begin (GtkDragSource *source, } } -static void -get_texture (GValue *value, - gpointer data) +static GdkContentProvider * +drag_prepare_texture (GtkDragSource *source, + double x, + double y, + GtkWidget *widget) { - GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data)); + GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget)); + + if (!GDK_IS_TEXTURE (paintable)) + return NULL; - if (GDK_IS_TEXTURE (paintable)) - g_value_set_object (value, paintable); + return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable); } -static void -get_file (GValue *value, - gpointer data) +static GdkContentProvider * +drag_prepare_file (GtkDragSource *source, + double x, + double y, + GtkWidget *widget) { + GdkContentProvider *content; GtkIconTheme *icon_theme; const char *name; GtkIconPaintable *info; - name = gtk_image_get_icon_name (GTK_IMAGE (data)); - icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (data))); + name = gtk_image_get_icon_name (GTK_IMAGE (widget)); + icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget)); info = gtk_icon_theme_lookup_icon (icon_theme, name, NULL, 32, 1, - gtk_widget_get_direction (GTK_WIDGET (data)), + gtk_widget_get_direction (widget), 0); - g_value_take_object (value, gtk_icon_paintable_get_file (info)); + content = gdk_content_provider_new_typed (G_TYPE_FILE, gtk_icon_paintable_get_file (info)); g_object_unref (info); + + return content; } static void setup_image_dnd (GtkWidget *image) { - GdkContentProvider *content; GtkDragSource *source; source = gtk_drag_source_new (); - content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image, NULL); - gtk_drag_source_set_content (source, content); - g_object_unref (content); + g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_texture), image); g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image); gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source)); } @@ -454,14 +460,10 @@ setup_image_dnd (GtkWidget *image) static void setup_scalable_image_dnd (GtkWidget *image) { - GdkContentProvider *content; GtkDragSource *source; source = gtk_drag_source_new (); - content = gdk_content_provider_new_with_callback (G_TYPE_FILE, get_file, image, NULL); - gtk_drag_source_set_content (source, content); - g_object_unref (content); - + g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_file), image); g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image); gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source)); } diff --git a/gdk/gdkcontentproviderimpl.c b/gdk/gdkcontentproviderimpl.c index 3be95cbed7..05857c75a6 100644 --- a/gdk/gdkcontentproviderimpl.c +++ b/gdk/gdkcontentproviderimpl.c @@ -322,118 +322,6 @@ gdk_content_provider_new_for_bytes (const char *mime_type, return GDK_CONTENT_PROVIDER (content); } -#define GDK_TYPE_CONTENT_PROVIDER_CALLBACK (gdk_content_provider_callback_get_type ()) -#define GDK_CONTENT_PROVIDER_CALLBACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK, GdkContentProviderCallback)) - -typedef struct _GdkContentProviderCallback GdkContentProviderCallback; -typedef struct _GdkContentProviderCallbackClass GdkContentProviderCallbackClass; - -struct _GdkContentProviderCallback -{ - GdkContentProvider parent; - - GType type; - GdkContentProviderGetValueFunc func; - gpointer data; - GDestroyNotify notify; -}; - -struct _GdkContentProviderCallbackClass -{ - GdkContentProviderClass parent_class; -}; - -GType gdk_content_provider_callback_get_type (void) G_GNUC_CONST; - -G_DEFINE_TYPE (GdkContentProviderCallback, gdk_content_provider_callback, GDK_TYPE_CONTENT_PROVIDER) - -static GdkContentFormats * -gdk_content_provider_callback_ref_formats (GdkContentProvider *provider) -{ - GdkContentProviderCallback *callback = GDK_CONTENT_PROVIDER_CALLBACK (provider); - - return gdk_content_formats_new_for_gtype (callback->type); -} - -static gboolean -gdk_content_provider_callback_get_value (GdkContentProvider *provider, - GValue *value, - GError **error) -{ - GdkContentProviderCallback *callback = GDK_CONTENT_PROVIDER_CALLBACK (provider); - - if (G_VALUE_HOLDS (value, callback->type) && callback->func != NULL) - { - callback->func (value, callback->data); - return TRUE; - } - - return GDK_CONTENT_PROVIDER_CLASS (gdk_content_provider_callback_parent_class)->get_value (provider, value, error); -} - -static void -gdk_content_provider_callback_dispose (GObject *gobject) -{ - GdkContentProviderCallback *self = GDK_CONTENT_PROVIDER_CALLBACK (gobject); - - if (self->notify != NULL) - self->notify (self->data); - - self->func = NULL; - self->data = NULL; - self->notify = NULL; - - G_OBJECT_CLASS (gdk_content_provider_callback_parent_class)->dispose (gobject); -} - -static void -gdk_content_provider_callback_class_init (GdkContentProviderCallbackClass *class) -{ - GdkContentProviderClass *provider_class = GDK_CONTENT_PROVIDER_CLASS (class); - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - - gobject_class->dispose = gdk_content_provider_callback_dispose; - - provider_class->ref_formats = gdk_content_provider_callback_ref_formats; - provider_class->get_value = gdk_content_provider_callback_get_value; -} - -static void -gdk_content_provider_callback_init (GdkContentProviderCallback *content) -{ -} - -/** - * gdk_content_provider_new_for_callback: (constructor) - * @type: the type that the callback provides - * @func: (not nullable): callback to populate a #GValue - * @data: (closure): data that gets passed to @func - * @notify: a function to be called to free @data when the content provider - * goes away - * - * Create a content provider that provides data that is provided via a callback. - * - * Returns: a new #GdkContentProvider - **/ -GdkContentProvider * -gdk_content_provider_new_with_callback (GType type, - GdkContentProviderGetValueFunc func, - gpointer data, - GDestroyNotify notify) -{ - GdkContentProviderCallback *content; - - g_return_val_if_fail (func != NULL, NULL); - - content = g_object_new (GDK_TYPE_CONTENT_PROVIDER_CALLBACK, NULL); - content->type = type; - content->func = func; - content->data = data; - content->notify = notify; - - return GDK_CONTENT_PROVIDER (content); -} - #define GDK_TYPE_CONTENT_PROVIDER_CALLBACK2 (gdk_content_provider_callback2_get_type ()) #define GDK_CONTENT_PROVIDER_CALLBACK2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CONTENT_PROVIDER_CALLBACK2, GdkContentProviderCallback2)) diff --git a/gdk/gdkcontentproviderimpl.h b/gdk/gdkcontentproviderimpl.h index c10158e5bb..907ed5015c 100644 --- a/gdk/gdkcontentproviderimpl.h +++ b/gdk/gdkcontentproviderimpl.h @@ -38,15 +38,6 @@ GDK_AVAILABLE_IN_ALL GdkContentProvider * gdk_content_provider_new_for_bytes (const char *mime_type, GBytes *bytes); -typedef void (*GdkContentProviderGetValueFunc) (GValue *value, - gpointer data); - -GDK_AVAILABLE_IN_ALL -GdkContentProvider * gdk_content_provider_new_with_callback (GType type, - GdkContentProviderGetValueFunc func, - gpointer data, - GDestroyNotify notify); - typedef GBytes * (*GdkContentProviderGetBytesFunc) (const char *mime_type, gpointer data); diff --git a/gtk/gtkcolorbutton.c b/gtk/gtkcolorbutton.c index 7ae781cd47..4d304c1a46 100644 --- a/gtk/gtkcolorbutton.c +++ b/gtk/gtkcolorbutton.c @@ -285,12 +285,15 @@ gtk_color_button_drag_begin (GtkDragSource *source, g_object_unref (paintable); } -static void -get_rgba_value (GValue *value, - gpointer data) +static GdkContentProvider * +gtk_color_button_drag_prepare (GtkDragSource *source, + double x, + double y, + GtkColorButton *button) { - GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (GTK_COLOR_BUTTON (data)); - g_value_set_boxed (value, &priv->rgba); + GtkColorButtonPrivate *priv = gtk_color_button_get_instance_private (button); + + return gdk_content_provider_new_typed (GDK_TYPE_RGBA, &priv->rgba); } static void @@ -300,7 +303,6 @@ gtk_color_button_init (GtkColorButton *button) PangoLayout *layout; PangoRectangle rect; GdkContentFormats *targets; - GdkContentProvider *content; GtkDragSource *source; GtkDropTarget *dest; @@ -333,9 +335,7 @@ gtk_color_button_init (GtkColorButton *button) gdk_content_formats_unref (targets); source = gtk_drag_source_new (); - content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, button, NULL); - gtk_drag_source_set_content (source, content); - g_object_unref (content); + g_signal_connect (source, "prepare", G_CALLBACK (gtk_color_button_drag_prepare), button); g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_button_drag_begin), button); gtk_widget_add_controller (priv->button, GTK_EVENT_CONTROLLER (source)); diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c index e66caa63e3..4a2ad7e93b 100644 --- a/gtk/gtkcolorswatch.c +++ b/gtk/gtkcolorswatch.c @@ -578,12 +578,15 @@ static const char *dnd_targets[] = { "application/x-color" }; -static void -get_rgba_value (GValue *value, - gpointer data) +static GdkContentProvider * +gtk_color_swatch_drag_prepare (GtkDragSource *source, + double x, + double y, + GtkColorSwatch *swatch) { - GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (GTK_COLOR_SWATCH (data)); - g_value_set_boxed (value, &priv->color); + GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch); + + return gdk_content_provider_new_typed (GDK_TYPE_RGBA, &priv->color); } void @@ -594,13 +597,10 @@ gtk_color_swatch_set_rgba (GtkColorSwatch *swatch, if (!priv->has_color) { - GdkContentProvider *content; GtkDragSource *source; source = gtk_drag_source_new (); - content = gdk_content_provider_new_with_callback (GDK_TYPE_RGBA, get_rgba_value, swatch, NULL); - gtk_drag_source_set_content (source, content); - g_object_unref (content); + g_signal_connect (source, "prepare", G_CALLBACK (gtk_color_swatch_drag_prepare), swatch); g_signal_connect (source, "drag-begin", G_CALLBACK (gtk_color_swatch_drag_begin), swatch); gtk_widget_add_controller (GTK_WIDGET (swatch), GTK_EVENT_CONTROLLER (source)); -- 2.30.2